home *** CD-ROM | disk | FTP | other *** search
/ TOS Silver 2000 / TOS Silver 2000.iso / Spiele / GEMSPIEL / COLTRIS / SOURCES / COLUMNS.C < prev    next >
Encoding:
C/C++ Source or Header  |  1995-01-27  |  9.2 KB  |  452 lines

  1. #include "cltr.h"
  2.  
  3. void dr_vdi(int x,int y,int col,int x_off,int y_off);
  4.  
  5. /*
  6.     assembler routinen zum kopieren eines blockes in den puffer
  7. */
  8.  
  9. #define WIDTH        6                /* breite des spielfeldes in blöcken */
  10. #define HEIGHT        16                /* höhe */
  11.         /* FIRSTCOLUMN=1, hardcoded */
  12. #define FIRSTLINE    4                /* erste angezeigte zeile */
  13. #define XWIDTH        (WIDTH+2)        /* breite des internen feldes */
  14. #define XHEIGHT        (HEIGHT+FIRSTLINE+1)    /* höhe */
  15.  
  16. int feld[XHEIGHT][XWIDTH];
  17.  
  18. void columns_preview(void);
  19. void dr_cstat(int x,int y,int dy);
  20. uint do_columns(void);
  21.  
  22. GAME columns=
  23. {
  24.     "Columns",
  25.     columns_preview,
  26.     dr_cstat,
  27.     do_columns,
  28.     WIDTH,
  29.     HEIGHT,
  30.     FIRSTLINE,
  31.     2,
  32.     4,
  33. };
  34.  
  35. /*
  36.     beschreibung eines steins
  37. */
  38. typedef struct {
  39.     int x;
  40.     int y;
  41.     int c[3];
  42. } STONE;
  43.  
  44. static STONE stone,next;
  45.  
  46. /*
  47.     lösche stein in puffer
  48. */
  49. static void rm_stone(void)
  50. {
  51. int i,y;
  52.  
  53.     for ( i=0; i<3; i++ ) {
  54.         y=stone.y+i;
  55.         if ( y>=FIRSTLINE )
  56.             columns.dr_block(stone.x,y,0);
  57.     }
  58. }
  59.  
  60. /*
  61.     zeichne stein in puffer
  62. */
  63. static void dr_stone(void)
  64. {
  65. int i,y;
  66.     for ( i=0; i<3; i++ ) {
  67.         y=stone.y+i;
  68.         if ( y>=FIRSTLINE )
  69.             columns.dr_block(stone.x,y,stone.c[i]);
  70.     }
  71. }
  72.  
  73. /*------------------------------------------------------------------------------
  74.  
  75.     preview
  76.  
  77. ------------------------------------------------------------------------------*/
  78. static void columns_preview(void)
  79. {
  80. int i;
  81.  
  82.     for ( i=0; i<3; i++ )
  83.         dr_vdi(1,FIRSTLINE+i,next.c[i],prev_x+(prev_w-columns.block_w)/2,prev_y+(prev_h-columns.block_h*3)/2);
  84. }
  85.  
  86. /*------------------------------------------------------------------------------
  87.  
  88.     statistik
  89.  
  90. ------------------------------------------------------------------------------*/
  91. static void dr_cstat(int x,int y,int dy)
  92. {
  93. int i;
  94.  
  95.     x-=columns.block_w*2;
  96.     for ( i=1; i<7; i++,y+=dy )
  97.         dr_vdi(2,FIRSTLINE,i,x,y);
  98. }
  99.  
  100. /*------------------------------------------------------------------------------
  101.  
  102.     spiel initialisieren
  103.  
  104. ------------------------------------------------------------------------------*/
  105. static void init_feld(void)
  106. {
  107. int i,j;
  108.  
  109.     for ( i=0; i<XHEIGHT; i++ ) {
  110.         for ( j=0; j<XWIDTH; j++ )
  111.             feld[i][j]=0;
  112.         feld[i][0]=feld[i][XWIDTH-1]=-1;
  113.     }
  114.     for ( j=0; j<XWIDTH; j++ )
  115.         feld[XHEIGHT-1][j]=-1;
  116.  
  117.     for ( i=XHEIGHT-1-opts.opts[PM_COLUMNS].random; i<XHEIGHT-1; i++ ) {
  118.         for ( j=1; j<XWIDTH-1; j++ ) {
  119.             feld[i][j]=(int)(xrandom()%6+1);
  120.             columns.dr_block(j,i,feld[i][j]);
  121.         }
  122.     }
  123.     copy_out();
  124. }
  125.  
  126. /*
  127.     erzeuge neuen stein
  128. */
  129. static void init_stone(void)
  130. {
  131.     next.x=XWIDTH/2;
  132.     next.y=1;
  133.     next.c[0]=(int)(xrandom()%6+1);
  134.     next.c[1]=(int)(xrandom()%6+1);
  135.     next.c[2]=(int)(xrandom()%6+1);
  136. }
  137.  
  138. /*------------------------------------------------------------------------------
  139.  
  140.     position der steine testen
  141.         COLUMNS != TETRIS 
  142.     columns: teste akt. stein mit angabe gewünschter bewegung
  143. ------------------------------------------------------------------------------*/
  144. /*
  145.      test ob stein noch fallen kann
  146. */
  147. static int check_stone(STONE *stone)
  148. {
  149.     if ( feld[stone->y+3][stone->x]!=0 )
  150.         return 1;
  151.     return 0;
  152. }
  153.  
  154. /*
  155.     teste ob stein nach rechts/links darf
  156. */
  157. static int check_side(STONE *stone,int side)
  158. {
  159.     if ( feld[stone->y][stone->x+side]!=0 ||
  160.             feld[stone->y+1][stone->x+side]!=0 ||
  161.             feld[stone->y+2][stone->x+side]!=0 )
  162.         return 1;
  163.     return 0;
  164. }
  165.  
  166. /*
  167.     teste ob nichtsichbarer oberer rand leer
  168.         falls nicht -> game over
  169. */
  170. static int xcheck(void)
  171. {
  172. int i,j;
  173.  
  174.     for ( i=0; i<FIRSTLINE; i++ )
  175.         for ( j=1; j<XWIDTH-1; j++ )
  176.             if ( feld[i][j]!=0 )
  177.                 return 1;
  178.     return 0;
  179. }
  180.  
  181. /*
  182.     teste spielfeld ob steine entfernt werden können
  183.         entferne geg. steine
  184. */
  185. static int check_feld(uint *lines)
  186. {
  187. int flags[XHEIGHT][XWIDTH];
  188. int i,j;
  189. int ii;
  190. int done=0;
  191.  
  192.     memset(flags,0,sizeof(flags));
  193.     for ( i=FIRSTLINE; i<XHEIGHT-1; i++ ) {
  194.         for ( j=1; j<XWIDTH-1; j++ ) {
  195.             if ( feld[i][j]==0 )
  196.                 continue;
  197.             if ( feld[i][j]==feld[i-1][j] && feld[i][j]==feld[i+1][j] ) {
  198.                 if ( flags[i-1][j]==0 )
  199.                     { flags[i-1][j]=1; (*lines)++; }
  200.                 if ( flags[i][j]==0 )
  201.                     { flags[i][j]=1; (*lines)++; }
  202.                 if ( flags[i+1][j]==0 )
  203.                     { flags[i+1][j]=1; (*lines)++; }
  204.                 done=1;
  205.             }
  206.             if ( feld[i][j]==feld[i][j-1] && feld[i][j]==feld[i][j+1] ) {
  207.                 if ( flags[i][j-1]==0 )
  208.                     { flags[i][j-1]=1; (*lines)++; }
  209.                 if ( flags[i][j]==0 )
  210.                     { flags[i][j]=1; (*lines)++; }
  211.                 if ( flags[i][j+1]==0 )
  212.                     { flags[i][j+1]=1; (*lines)++; }
  213.                 done=1;
  214.             }
  215.             if ( feld[i][j]==feld[i-1][j-1] && feld[i][j]==feld[i+1][j+1] ) {
  216.                 if ( flags[i-1][j-1]==0 )
  217.                     { flags[i-1][j-1]=1; (*lines)++; }
  218.                 if ( flags[i][j]==0 )
  219.                     { flags[i][j]=1; (*lines)++; }
  220.                 if ( flags[i+1][j+1]==0 )
  221.                     { flags[i+1][j+1]=1; (*lines)++; }
  222.                 done=1;
  223.             }
  224.             if ( feld[i][j]==feld[i-1][j+1] && feld[i][j]==feld[i+1][j-1] ) {
  225.                 if ( flags[i-1][j+1]==0 )
  226.                     { flags[i-1][j+1]=1; (*lines)++; }
  227.                 if ( flags[i][j]==0 )
  228.                     { flags[i][j]=1; (*lines)++; }
  229.                 if ( flags[i+1][j-1]==0 )
  230.                     { flags[i+1][j-1]=1; (*lines)++; }
  231.                 done=1;
  232.             }
  233.         }
  234.     }
  235.     if ( done ) {
  236. #if SOUND_LEVEL>0
  237.         do_sound(S_REMOVE);
  238. #endif
  239.         for ( ii=8; ii<=columns.last_flash; ii++ ) {
  240.             init_wait();
  241.             for ( i=FIRSTLINE; i<XHEIGHT-1; i++ ) {
  242.                 for ( j=1; j<XWIDTH-1; j++ ) {
  243.                     if ( flags[i][j] )
  244.                         columns.dr_block(j,i,ii);
  245.                 }
  246.             }
  247.             copy_out();
  248.             do_wait(5);
  249.         }
  250.  
  251.         for ( j=1; j<XWIDTH-1; j++ ) {
  252.             for ( ii=i=XHEIGHT-2; ii>=FIRSTLINE; ii--,i-- ) {
  253.                 while ( flags[i][j]!=0 )
  254.                     i--;
  255.                 if ( i<0 )
  256.                     i=0;
  257.                 if ( i!=ii ) {
  258.                     feld[ii][j]=feld[i][j];
  259.                     columns.dr_block(j,ii,feld[ii][j]);
  260.                 }
  261.             }
  262.             for ( ; ii>=0; ii-- )
  263.                 feld[ii][j]=0;
  264.         }
  265.         copy_out();
  266.     }
  267.     return done;
  268. }
  269.  
  270. /*
  271.     haupt-spielroutine
  272.         returns 0 -> abbruch, 1 -> game over
  273. */
  274. static uint do_columns(void)
  275. {
  276. long time;
  277. int draw,let_it_fall,drop_line;
  278. uint level,delay;
  279. uint stones,lines,score;
  280. STONE x;
  281. KEY key;
  282. uint stat[6]={0,0,0,0,0,0};
  283.  
  284.     init_feld();
  285.     while ( check_feld(&lines) )        /* wg. preset */
  286.         ;
  287.  
  288.     level=opts.opts[PM_COLUMNS].start_level;
  289.     delay=calc_delay(level);
  290.     stones=lines=score=0;
  291.  
  292.     init_stone();
  293.  
  294.     while ( 1 ) {
  295.         stone=next;
  296.  
  297.         init_stone();
  298. #if SOUND_LEVEL>1
  299.         do_sound(S_NEW);
  300. #endif
  301.         if ( preview_flag )
  302.             redraw_preview(0l);
  303.  
  304.         stat[stone.c[0]-1]++;
  305.         stat[stone.c[1]-1]++;
  306.         stat[stone.c[2]-1]++;
  307.         dr_stat(stat);
  308.  
  309.         if ( check_stone(&stone) || xcheck() )    /* game over? */
  310.             break;
  311.         x=stone;                    /* stein merken */
  312.  
  313.         stones++;
  314.         if ( level<9 && lines>level*50+50 )
  315.             { level++; inv_feld(); delay=calc_delay(level); }
  316.         dr_score(level,lines,stones,score);
  317.  
  318.         let_it_fall=0;                /* nicht fallen lassen */
  319.         time=gettime();                /* zeit merken */
  320.         draw=1;                        /* zeichnen */
  321.  
  322.         while ( 1 ) {
  323.             if ( draw ) {            /* nur wenn nötig */
  324.                 dr_stone();            /* stein zeichnen */
  325.                 draw=0;                /* flag löschen */
  326.                 copy_out();
  327.             }
  328.  
  329.             if ( !let_it_fall )        /* falls fallen lassen */
  330.                 key=get_key();
  331.             else
  332.                 key=NO_KEY;            /* kein zeichen einlesen */
  333.  
  334.             switch ( key ) {
  335.               case K_QUIT:
  336.                 return 0;
  337.               /*break;*/
  338.               case K_LEFT:
  339.                 if ( !check_side(&x,-1) ) {
  340.                     x.x--;
  341. #if SOUND_LEVEL>3
  342.                     do_sound(S_LEFT);
  343.                 }
  344.                 else {
  345.                     do_sound(S_CANT_LEFT);
  346. #endif
  347.                 }
  348.               break;
  349.               case K_RIGHT:
  350.                 if ( !check_side(&x,+1) ) {
  351.                     x.x++;
  352. #if SOUND_LEVEL>3
  353.                     do_sound(S_RIGHT);
  354.                 }
  355.                 else {
  356.                     do_sound(S_CANT_RIGHT);
  357. #endif
  358.                 }
  359.               break;
  360.               case K_ROTATE: {
  361.                int i;
  362.                 i=x.c[2];
  363.                 x.c[2]=x.c[1];
  364.                 x.c[1]=x.c[0];
  365.                 x.c[0]=i;
  366. #if SOUND_LEVEL>3
  367.                     do_sound(S_ROTATE);
  368. #endif
  369.               } break;
  370.               case K_ROT_CCW: {
  371.                int i;
  372.                 i=x.c[0];
  373.                 x.c[0]=x.c[1];
  374.                 x.c[1]=x.c[2];
  375.                 x.c[2]=i;
  376. #if SOUND_LEVEL>3
  377.                     do_sound(S_ROT_CCW);
  378. #endif
  379.               } break;
  380.               case K_DROP:
  381.                 let_it_fall=1;
  382.                 drop_line=x.y;
  383. #if SOUND_LEVEL>2
  384.                     do_sound(S_DROP);
  385. #endif
  386.               break;
  387.               case K_LEVEL:
  388.                 if ( level<9 ) {
  389.                       level++;
  390.                     inv_feld();
  391.                     delay=calc_delay(level);
  392.                     dr_score(level,lines,stones,score);
  393.                 }
  394.               break;
  395.             }
  396.  
  397.             if ( gettime()>time+delay || (let_it_fall && gettime()>time+1) ) {
  398.                 if ( check_stone(&x) )/* eins tiefer */
  399.                     break;
  400.                 x.y++;
  401. #if SOUND_LEVEL>2
  402.                 if ( let_it_fall )
  403.                     do_sound(S_DROPDOWN);
  404.                 else
  405.                     do_sound(S_STEPDOWN);
  406. #endif
  407.                 time=gettime();
  408.             }
  409.             if ( memcmp(&x,&stone,sizeof(x)) ) {
  410.                 draw=1;                /* falls sich was getan hat */
  411.                 rm_stone();            /* stein neuzeichnen */
  412.                 stone=x;
  413.             }
  414.         }
  415.  
  416. #if SOUND_LEVEL>1
  417.         do_sound(S_DOWN);
  418. #endif
  419.         if ( memcmp(&x,&stone,sizeof(x)) ) {
  420.             rm_stone();            /* stein neuzeichnen */
  421.             stone=x;
  422.             dr_stone();
  423.             copy_out();
  424.         }
  425.                                     /* stein ist unten angekommen */
  426.                                     /* eintragen ins feld */
  427.         feld[stone.y][stone.x]=stone.c[0];
  428.         feld[stone.y+1][stone.x]=stone.c[1];
  429.         feld[stone.y+2][stone.x]=stone.c[2];
  430.  
  431.                                     /* steine wegräumen */
  432.         while ( check_feld(&lines) )
  433.             ;
  434.  
  435.                                     /* score berechnen */
  436.         score+=5+level*2;
  437.         if ( let_it_fall )
  438.             score+=XHEIGHT-1-drop_line;
  439.         else
  440.             score+=XHEIGHT-1-stone.y;
  441.         if ( preview_flag )
  442.             score-=3;
  443.  
  444.                                     /* tastaturpuffer löschen */
  445.         clr_keys();
  446.     }
  447.     clr_keys();
  448.  
  449.     dr_score(level,lines,stones,score);
  450.     return score;
  451. }
  452.